
#ifndef SYMBOLTABLE_H
#define SYMBOLTABLE_H

#include <string>
#include <sstream>
#include <fstream>
enum {
	SAVE_TYPE_STATIC,
	SAVE_TYPE_AUTO,
	SAVE_TYPE_FUNC,
	SAVE_TYPE_PARA
};

class SYMBOL {
public:
	std::string	name; //符号名
	int	level;    //作用层次
	int	dataType; //类型
	int	saveType; //存储类别
	unsigned long	offsetAddr; //相对存储区位移量
	
	SYMBOL			*nextPara; //下一个参数，用于函数定义
	SYMBOL			*nextStructMember; //下一个结构成员，用于结构体变量
	SYMBOL			*xiaTui;	//指向下推符号链
	SYMBOL			*next;		//指向下一符号表项
	SYMBOL(const std::string &symbolName, int dataType, 
		int level) {
		name = symbolName;			//符号名
		this->dataType = dataType;  //类型
		this->level = level;		//层次
		saveType = SAVE_TYPE_STATIC; 
		offsetAddr = 0;
		nextPara = NULL;
		nextStructMember = NULL;
		xiaTui = NULL;
		next = NULL;
	}
	const std::string getStrAddr(void) const {
		std::ostringstream strAddr; //整合类型后的线性地址
		switch(saveType) {
			case SAVE_TYPE_STATIC:
				strAddr << "Static+";
				break;
			case SAVE_TYPE_AUTO:
				strAddr << "Auto+";
				break;
			case SAVE_TYPE_FUNC:
				strAddr << "Text+";
				break;
			case SAVE_TYPE_PARA:
				strAddr << "Stack+";
				break;
			default:
				throw "不合法的符号存储类型";
		}
		strAddr << offsetAddr;
		return strAddr.str();
	}
};

class SymbolTable {

	SYMBOL *head; //采用后进先出链表

	SYMBOL *rightPara; //指向右邻参数符号表项

	unsigned long autoAddr; //自动地址(堆栈地址)
	unsigned long staticAddr; //静态地址(数据段地址)
	unsigned long paraAddr; //参数地址
	unsigned long tempAddr; //临时变量地址
	int currentLevel;//当前层次

	std::ostringstream errMsg; //错误信息
	std::ofstream out;

public:
	SymbolTable();
	~SymbolTable();

	//将指定的符号名、类型加入到符号表中：
	void insertVar(const std::string &varName, int dataType);

	//将指定的函数名、返回值类型、以及入口地址加入符号表中：
	void insertFunc(const std::string &funcName, int retType,
		unsigned long addr);

	//将指定的函数参数名、类型加入函数表中：
	void insertPara(const std::string &paraName, int dataType);

	//搜索指定符号名表项，返回符号地址：
	const SYMBOL * searchVar(const std::string &varName);

	//搜索指定函数名表项，返回符号地址：
	const SYMBOL * searchFunc(const std::string &funcName);

	//分配一临时变量，返回其地址：
	const std::string newTemp(void);

	//释放n个临时变量空间：
	void deleteTemp(void);

	//进入"{":
	void inBracket(void);

	//跳出"}":
	void outBracket(void);

	//显示当前符号表的内容
	void printTable(void);
};


#endif  //end of SYMBOLTABLE_H


